#include "server.h"

#include "messaging/endpoint.h"
#include "messaging/drivers/drivers.h"
#include "messaging/exception.h"


namespace evm { namespace messaging {


void RPCDispatcher::operator()(IncomingMsgPtr incoming) {
    incoming->acknowledge();
    try {
        incoming->reply(dispatch(incoming->message));
    }
    catch (const exception& e) {  //TODO: exception should be customized
        log_error(e.what());
        incoming->reply_error(e.what());
    }
}

Json RPCDispatcher::dispatch(const Json &message) {
    const string method = message["method"];
    const auto& args = message["args"];
    const string namespace_ = message["namespace"];

    for (auto& endpoint: endpoints) {
        auto target = endpoint->target;

        if (!target)
            target = default_target;

        if (target->namespace_ != namespace_)
            continue;

        if (endpoint->has(method))
            return (*endpoint)(method, args);
    }

    throw runtime_error("Method '" + method + "' in namespace '" + namespace_ + "' not found.");
}

MessageServerPtr get_rpc_server(TransportPtr transport,
                                TargetPtr target, Endpoints endpoints)
{
    auto dispatcher = DispatcherPtr(new RPCDispatcher(target, endpoints));
    return make_shared<MessageServer>(transport, dispatcher);
}

}}
